import DB = require("nedb");

class DataStore<T> {
  db: DB;

  constructor() {
    this.db = new DB();
  }

  async find(query: object): Promise<T[]> {
    const result = await this.db.find(query);

    return new Promise((resolve, reject) => {
      if (result) {
        result.exec((_err: Error | null, data: T[]) => {
          resolve(data);
        });
      } else {
        reject("Error in DataStore.find()");
      }
    });
  }

  async findOne(query: object): Promise<T> {
    const result = await this.find(query);

    return new Promise((resolve, reject) => {
      if (result.length >= 1) {
        resolve(result[0]);
      } else {
        reject("Error in DataStore.findOne()");
      }
    });
  }

  async add(record: T): Promise<void> {
    await this.db.insert(record);
  }

  async update(oldRecord: T, newRecord: T): Promise<void> {
    this.db.update(oldRecord, newRecord);
  }

  async delete(record: T): Promise<void> {
    this.db.remove(record);
  }

  createQuery<T extends object, K extends keyof T>(obj: T, key: K): object {
    const value = obj[key];

    if (typeof value === "number") {
      return JSON.parse(`{"${key.toString()}": ${value}}`);
    } else {
      return JSON.parse(`{"${key.toString()}": "${value}"}`);
    }
  }
}

export { DataStore };
